/**
 * @file I2CA.c
 * @author      JinChengLong (https://gitee.com/Datejin/)
 * @brief       软件模拟I2C通讯
 * @version     0.1
 * @date        2023
 * 
 * @copyright   Copyright © 2025 by JinChengLong 
 * 
 * All rights reserved.
 * Unauthorized copying, reproduction, or redistribution of this file via any medium is strictly prohibited.  
 * Proprietary and confidential.
 *   
 */
#include "I2CA.h"
#include "Delay.h"


//软件I2C，手动反转电平，来接受数据和传输数据

//宏定义

/**
 * @brief I2C时钟
 * 
 * @param BitValue 
 */
void I2CA_W_SCL(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);		//BitValue强转换为BitAction类型
	Delay_us(10);						//引脚反转速度保证能跟上//I2C足够慢不能太快
}

/**
 * @brief I2C数据线写
 * 
 * @param BitValue 
 */
void I2CA_W_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);		//BitValue强转换为BitAction类型
	Delay_us(10);						//引脚反转速度保证能跟上//I2C足够慢不能太快
}

/**
 * @brief I2C数据线读
 * 
 * @return uint8_t 
 */
uint8_t I2CA_R_SDA(void)
{
	uint8_t BitValue;
	BitValue=GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
	Delay_us(10);
	return BitValue;	
}




/**
 * @brief 软件I2C初始化
 * 
 */
void I2CA_init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;				//
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;			//开漏输出，防止短路
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11);		//先置高电平//释放总线
}


//
/**
 * @brief I2C起始条件
 * 
 */
void I2CA_start(void)
{ 
	I2CA_W_SDA(1);		//需要兼容重复起始条件Sr，SCL是低电平，SDA电平不确定，趁着SCL是低电平先释放SDA再释放SCL，然后再拉低SDA,SCL
	I2CA_W_SCL(1);	
	I2CA_W_SDA(0);
	I2CA_W_SCL(0);
	
}
//
/**
 * @brief I2C终止条件
 * 
 */
void I2CA_stop(void)
{ 
	//时序单元开始时，应先拉低SDA，再释放SCL，SDA并不一定是低电平，确保释放SDA能产生上升沿
	I2CA_W_SDA(0);	
    I2CA_W_SCL(1);	
    I2CA_W_SDA(1);//回归高电平
}


//
/**
 * @brief I2C发送字节
 * 
 */
void I2CA_sendbyte(uint8_t byte)
{
	uint8_t i;
	for(i=0;i<8;i++)
	{
		I2CA_W_SDA(byte & (0x80 >> i) );//按位与取出数据的最高位(先右移i位)//0x80=10000000
		I2CA_W_SCL(1);			//从机立刻读取SDA
		I2CA_W_SCL(0);
	}
	

} 

//
/**
 * @brief I2C接受数据
 * 
 */
uint8_t I2CA_receivebyte(void)
{
	uint8_t	i, byte=0x00;
	I2CA_W_SDA(1);			
	
	
	for(i=0;i<8;i++)
	{
		I2CA_W_SCL(1);//通信是有从机的参与，从机随主机时钟，有义务的改变SDA电平
		if(I2CA_R_SDA()==1)
		{
			byte|=(0x80>>i);	//byte最高位置一
		}
		I2CA_W_SCL(0);//
	}
	
	return byte ;
} 

//
/**
 * @brief I2C发送字节应答
 * 
 */
void I2CA_sendACK(uint8_t ACKbit)
{
	
	I2CA_W_SDA(ACKbit);//ACKbit 放在SDA上
		I2CA_W_SCL(1);			//从机立刻读取应答
		I2CA_W_SCL(0);

	

} 

//
/**
 * @brief I2C接受数据应答
 * 
 */
uint8_t I2CA_receiveACK(void)
{
	uint8_t	 ACKbit;
	I2CA_W_SDA(1);	//从机把应答位放在SDA上
	//开漏加弱上拉，主机输出1，SDA不强制为高电平，而是释放SDA 
	//主机释放SDA，从机有义务将其拉低
	I2CA_W_SCL(1);//读取应答位
	ACKbit=I2CA_R_SDA();
	I2CA_W_SCL(0);//下一个时序单元
	return ACKbit ;
} 





